package info.marlan.sim;

import info.marlan.sim.util.DBHelper;
import info.marlan.sim.util.DBHelper.Answer;
import info.marlan.sim.util.DBHelper.Question;
import info.marlan.view.StatusBar;
import info.marlan.view.TransparentPanel;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.CompoundButton.OnCheckedChangeListener;



public class Test extends Activity {
    private DBHelper dbHelper;
    private SharedPreferences preferences;
    private TestState state;
    private Handler handler = new Handler();
    private TextView timer;
    private String intro;
    private String languagecode;
    private boolean enableFreeTextAnswers;
    private boolean saveScore = true;
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	
		 preferences =
			 Test.this.getSharedPreferences(
	        	Constants.PREFERENCES, Context.MODE_PRIVATE);
		
		languagecode = preferences.getString(Constants.PREFERENCES_LANGUAGE, Constants.PREFERENCES_DEFAULT_LANGUAGE); 
		enableFreeTextAnswers = preferences.getBoolean(Constants.PREFERENCES_ENABLE_FREETEXT_ANSWERS, Constants.PREFERENCES_DEFAULT_ENABLE_FREETEXT_ANSWERS);
		
		timer = new TextView(this);
		timer.setGravity(Gravity.RIGHT);
		
		if(savedInstanceState != null){
			 state = (TestState) savedInstanceState.getSerializable(Constants.STATE);
			 buildQuestionView();
			 handler.removeCallbacks(updateTimeTask);
             handler.postDelayed(updateTimeTask, 100);
		}else{
		    dbHelper = new DBHelper(Test.this);
			state = new TestState();
			state.name = getIntent().getStringExtra(ObjectiveDialog.NAME);
			String condition = null;
			String name = null;
			String limit = null;
			String freeTextCondition = enableFreeTextAnswers ? "" : " and (freeTextAnswer is null or freeTextAnswer='')";
			if( state.name.length()>5){
				condition = " languagecode=? and category=?  " + freeTextCondition;
				name = state.name;
			}else{
				condition = " languagecode=? and category like ? " + freeTextCondition;
				name = state.name+"%";
				limit = "10";
			}
						
			state.questions = dbHelper.getQuestions(condition, 
		    		 new String[]{languagecode,
					name}," Random() ",limit);
		    dbHelper.cleanup();
			state.runtime = (long)(state.questions.size() * 1.4 )*(60 * 1000);
			if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
				intro = getString(R.string.count_questions_de).replace("${questions}", "" + state.questions.size()) +"\n"+ getString(R.string.copyright_de);
			}else{
				intro = getString(R.string.count_questions_en).replace("${questions}", "" + state.questions.size()) +"\n"+ getString(R.string.copyright_en);
			}
			showDialog(0);
		}
		 	
	}

	/**
	 * Displays the evaluation screen.
	 */
	public void showEvaluation(){
		state.freeze=true;
		
		if(!state.isSaved){
			dbHelper = new DBHelper(Test.this);
			if(saveScore){
				dbHelper.updateStats(state);
			}
			state.setStats(dbHelper.getStats(state.name));
			dbHelper.cleanup();
			state.isSaved=true;
		}
		ScrollView s = new ScrollView(this);
		s.setPadding(4, 8, 4, 4);
		LinearLayout l = new LinearLayout(this);
		l.setLayoutParams(
			new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT));
		l.setOrientation(LinearLayout.VERTICAL);
		
		int correctAnswers = state.getCorrectAnswers();
		int possiblePoints = state.getPossiblePoints();
		int points = state.getPoints();
		int percentage = points*100/possiblePoints;
		
		StringBuffer evaluationText = new StringBuffer();	
		String evaluation = null;
		if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
			evaluation = getString(R.string.evaluation_text_de) +"\n"+ getString(R.string.percent_de);			
		}else{
			evaluation = getString(R.string.evaluation_text_en)+"\n"+ getString(R.string.percent_en);
		}
		evaluationText.append(evaluation
				.replace("${correctAnswers}", ""+correctAnswers)
				.replace("${questions.size}", ""+state.questions.size())
				.replace("${possiblepoints}", ""+possiblePoints)
				.replace("${points}", ""+points)
				.replace("${percentage}", "" + percentage) );
		
		addPanel(l,evaluationText.toString(),percentage);
		
		
		if(state.getStat(3) > 0){
			int overallPercentage = state.getStat(2)*100/state.getStat(3);
			String overall = null;
			if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
				overall = getString(R.string.percentoverall_de);
			}else{
				overall = getString(R.string.percentoverall_en);
			}
			StringBuffer overallText = new StringBuffer();	
			overallText.append(overall.replace("${exam}",(state.name.startsWith("1")?"LPIC 1":"LPIC 2")).
			replace("${percentage}", "" + overallPercentage).
			replace("${questions}", "" + state.getStat(0)).
			replace("${points}", "" + state.getStat(2)).
		    replace("${possiblepoints}", "" + state.getStat(3)).
		    replace("${correct}", "" + state.getStat(1)));
			
			addPanel(l,overallText.toString(),overallPercentage);
		}
	
		
		Button showAnswers = new Button(this);
		showAnswers.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
            	state.freeze=true;
            	state.question=0;
            	buildQuestionView();
            }
        }); 
		if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
			showAnswers.setText(R.string.show_questions_de);
		}else{
			showAnswers.setText(R.string.show_questions_en);
		}
		l.addView(showAnswers);
		
		
		Button endTest = new Button(this);
		endTest.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
            	Test.this.finish();
            }
        }); 
		if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
			endTest.setText(R.string.finish_exam_de);
		}else{
			endTest.setText(R.string.finish_exam_en);
		}
		l.addView(endTest);


		s.addView(l);
		
		setContentView(s);
		
	}

	/**
	 * Builds the view for one question.
	 */
	public void buildQuestionView(){
	
		
		if( state.question >= state.questions.size()){
			showEvaluation();
			return;
		}
		
		Question question = state.questions.get(state.question);
		int correctAnswers = question.countCorrectAnswers();
		TextView q = new TextView(this);
		
		q.setText(question.question.replaceAll("<br>", "\n"));
		
		q.setTypeface(Typeface.DEFAULT);
		q.setTextColor(Color.WHITE);
		//q.setTextSize(16);

	
		
		ScrollView s = new ScrollView(this);

		s.setPadding(4, 8, 4, 4);
		LayoutParams layout = new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT);
		s.setLayoutParams(layout);
		LinearLayout l = new LinearLayout(this);
		
		addStatusBar(l);
		
		l.setLayoutParams(layout);
		l.setOrientation(LinearLayout.VERTICAL);
		
		l.addView(q);
		
		switch(correctAnswers){
		case 0:addFreetext(l, question) ;break;
		case 1:addRadioGroup(l, question);break;
		default:addCheckBoxes(l, question);
		}
		if(state.freeze && question.explanation!=null && question.explanation.length()>2){
			TextView e = new TextView(this);
			e.setText(question.question);
			e.setTypeface(Typeface.DEFAULT);
			e.setTextColor(Color.WHITE);
			e.setText(question.getExplanation());
			l.addView(e);
		}
		
		addnavigation(l);
	
		s.addView(l);
		
		setContentView(s);
	}
	
	public void addPanel(ViewGroup view,String text, int percent){
		TextView q = new TextView(this);
		q.setText(text);
		q.setTypeface(Typeface.DEFAULT);
		q.setTextColor(Color.WHITE);
		q.setGravity(Gravity.LEFT);
		q.setPadding(5, 5, 5, 5);
		TransparentPanel panel = new TransparentPanel(this);
		LinearLayout.LayoutParams mlp = new LinearLayout.LayoutParams(
                new ViewGroup.MarginLayoutParams(
                                LinearLayout.LayoutParams.FILL_PARENT,
                                LinearLayout.LayoutParams.FILL_PARENT));
		mlp.setMargins(0, 10, 0, 10);
		panel.setLayoutParams(mlp);
		panel.setPadding(5, 5, 5, 5);
		panel.setGravity(Gravity.LEFT);
		StatusBar statusbar = new StatusBar(this);
		statusbar.setPercent(percent);
		panel.addView(statusbar);
		panel.addView(q);
	
		panel.setOrientation(LinearLayout.HORIZONTAL);
		view.addView(panel);
	}
	
	/**
	 * Appends the statusbar.
	 * @param view
	 */
	private void addStatusBar(ViewGroup view){
		TableLayout table = new TableLayout(this);
		table.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT));
		table.setStretchAllColumns(true);
		TableRow row =  new TableRow(this);
		TextView counter = new TextView(this);
		counter.setText( (state.question+1) + " / " + state.questions.size());
		row.addView(counter);
	
		
		TextView question = new TextView(this);
		question.setText( state.name);
		row.addView(question);
		
		if(timer!=null){
			ViewGroup parent =(ViewGroup)	timer.getParent();
			if(parent!=null){
				parent.removeAllViews();
			}
		}
		
		row.addView(timer);

		table.addView(row);
		TransparentPanel panel = new TransparentPanel(this);
		LinearLayout.LayoutParams mlp = new LinearLayout.LayoutParams(
                new ViewGroup.MarginLayoutParams(
                                LinearLayout.LayoutParams.WRAP_CONTENT,
                                LinearLayout.LayoutParams.WRAP_CONTENT));
		mlp.setMargins(0, 0, 0, 10);

		panel.setLayoutParams(mlp);
		panel.setPadding(5, 5, 5, 5);
		panel.addView(table);
		view.addView(panel);
		
	}
	/**
	 * Appends the navigation.
	 * @param view
	 */
	private void addnavigation(ViewGroup view){
		
		TableLayout table = new TableLayout(this);
		table.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT));
		table.setStretchAllColumns(true);
		TableRow row =  new TableRow(this);
		
		Button backward = new Button(this);
		backward.setText("<<");

		if(state.question==0){
			backward.setEnabled(false);	
		}
		//b.setGravity(Gravity.BOTTOM);
		//b.setMaxEms(30);
		backward.setOnClickListener(new OnClickListener() {
	            public void onClick(View v) {
	            	if(state.question > 0){
	            		state.question--;
	            	}
	            	buildQuestionView();
	            }
	        }); 
		
		Button stop = new Button(this);
		if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
			stop.setText(R.string.finish_exam_de);
		}else{
			stop.setText(R.string.finish_exam_en);
		}
		stop.setOnClickListener(new OnClickListener() {
	            public void onClick(View v) {
	            	if(!state.freeze){
	            		showDialog(1);
	            	}else{
	            		showEvaluation();
	            	}
	            }
	        }); 
		
		Button forward = new Button(this);
		if( state.question >= state.questions.size()-1){
			if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
				forward.setText(R.string.show_evaluation_de);
			}else{
				forward.setText(R.string.show_evaluation_en);	
			}
		}else{
			forward.setText(">>");
		}
		//b.setGravity(Gravity.BOTTOM);
		//b.setMaxEms(30);
		forward.setOnClickListener(new OnClickListener() {
	            public void onClick(View v) {
	            	state.question++;
	            	buildQuestionView();
	            }
	        }); 
		row.addView(backward);
		row.addView(stop);
		row.addView(forward);
		table.addView(row);
		

		TransparentPanel panel = new TransparentPanel(this);
		 
		LinearLayout.LayoutParams mlp = new LinearLayout.LayoutParams(
                new ViewGroup.MarginLayoutParams(
                                LinearLayout.LayoutParams.WRAP_CONTENT,
                                LinearLayout.LayoutParams.WRAP_CONTENT));
		mlp.setMargins(0, 10, 0, 20);
		
		panel.setLayoutParams(mlp);
		panel.setPadding(5, 5, 5, 5);
		panel.addView(table);
		view.addView(panel);
		//view.addView(table);
		
	}
	
	
	private void addCheckBoxes(ViewGroup view,final Question question){
		LayoutParams layout = new LayoutParams(LayoutParams.FILL_PARENT,
	                LayoutParams.FILL_PARENT);
		int i = 0;
		for(final Answer answer: question.shuffledAnswers){
			i++;
			CheckBox c = new CheckBox(this);
			c.setLayoutParams(layout);
			c.setOnCheckedChangeListener(new OnCheckedChangeListener()
			{
			    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
			    {
			        	answer.state = isChecked;
			    }
			});
			c.setBackgroundColor(Color.DKGRAY);
			if(state.freeze){
				c.setEnabled(false);
				if(answer.correct==false && answer.state==true){
					c.setBackgroundColor(Color.RED);
					c.setTextColor(Color.BLACK);
				}
				if(answer.correct==true){
					c.setBackgroundColor(Color.GREEN);
					c.setTextColor(Color.BLACK);
				}
			}
			c.setId(answer.id);
			c.setChecked(answer.state);
			c.setText(i + ") " + answer.answer);
			c.setTypeface(Typeface.DEFAULT);
			c.setTextSize(14);
			view.addView(c);
	
		}
	}
	
	
	private void addRadioGroup(ViewGroup view,final Question question){
		RadioGroup group = new RadioGroup(this);
		LayoutParams layout = new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT);
//		LinearLayout.LayoutParams mlp = new LinearLayout.LayoutParams(
//                new ViewGroup.MarginLayoutParams(
//                                LinearLayout.LayoutParams.FILL_PARENT,
//                                LinearLayout.LayoutParams.WRAP_CONTENT));
//		mlp.setMargins(0, 20, 0, 50);
		
		group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
		{
		    public void onCheckedChanged(RadioGroup group, int checkedId)
		    {
		    	for(Answer answer: question.shuffledAnswers){
		    		if(checkedId == (answer.id)){
		    			answer.state = true;
		    		}else{
		    			answer.state = false;
		    		}
		    	}
		    }
		});
		int i = 0;
		int checked = 0;
		for(Answer answer: question.shuffledAnswers){
			i++;
			RadioButton r = new RadioButton(this);
			r.setLayoutParams(layout);
			r.setText(i + ") " + answer.answer);
			r.setTextSize(14);
			r.setId(answer.id);
			r.setTypeface(Typeface.DEFAULT);
			r.setBackgroundColor(Color.DKGRAY);
			//r.setLayoutParams(mlp);
			if(state.freeze){
				r.setEnabled(false);
				if(answer.correct==false && answer.state==true){
					r.setBackgroundColor(Color.RED);
					r.setTextColor(Color.BLACK);
				}
				if(answer.correct==true){
					r.setBackgroundColor(Color.GREEN);
					r.setTextColor(Color.BLACK);
				}
			}	
			if(answer.state){
				checked = answer.id;
			}
			
			group.addView(r);
		}
		if(	checked	>	0	){
			group.clearCheck();
			group.check(checked);
		}
		view.addView(group);
	}
	
	
	
	private void addFreetext(ViewGroup view,final Question question){
		final EditText text = new EditText(this);
		if(question.freeTextAnswerState != null){
			text.setText(question.freeTextAnswerState);
		}
		text.addTextChangedListener(new TextWatcher(){
		
			@Override
			public void afterTextChanged(Editable s) {
				if( s != null && !s.toString().equals(question.freeTextAnswerState)){
					question.freeTextAnswerState = s.toString();
				}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
			}
			
		});
		if(state.freeze){
			text.setEnabled(false);
			if(question.answeredCorrect()){
				text.setBackgroundColor(Color.GREEN);
			}else{
				text.setBackgroundColor(Color.RED);
				TextView correctAnswer = new TextView(this);
				correctAnswer.setTextSize(text.getTextSize());
				correctAnswer.setPadding(5, 0, 0, 5);
				if(Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)){
					correctAnswer.setText((question.type==Constants.QUESTION_TYPE_SORT_REGEX ?  getString( R.string.correct_answer_regex_de ) : getString( R.string.correct_answer_de )) + "\n" + question.freeTextAnswer);
				}else{
					correctAnswer.setText( (question.type==Constants.QUESTION_TYPE_SORT_REGEX ?  getString( R.string.correct_answer_regex_en ) : getString( R.string.correct_answer_en ))+ "\n" + question.freeTextAnswer);
				}
				view.addView(correctAnswer);
			}
		}
		view.addView(text);
	}
	
    @Override
    protected Dialog onCreateDialog(int id) {
    	
    	if(state.questions==null || state.questions.size() < 1){
    		String oops = Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)? getString(R.string.no_question_de):getString(R.string.no_question_en);
    		return 	new AlertDialog.Builder(Test.this)
            .setTitle("Sorry").setMessage(oops)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                   handler.removeCallbacks(updateTimeTask);
                   Test.this.finish();
                }
            })
            .create();
    	}
    	if(id==1){
    		String saveScoreTitle = Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)? 
    				getString(R.string.save_de):getString(R.string.save_en);
    		String saveScore = Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)? 
    				getString(R.string.save_score_de):getString(R.string.save_score_en);
    		String yes = Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)? 
    				getString(R.string.yes_de):getString(R.string.yes_en);
    		String no = Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)? 
    				getString(R.string.no_de):getString(R.string.no_en);
    		return 	new AlertDialog.Builder(Test.this)
            .setTitle(saveScoreTitle).setMessage(saveScore)
            .setNegativeButton(no, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                   Test.this.saveScore = false;
                   showEvaluation();
                }
            }).setPositiveButton(yes, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    Test.this.saveScore = true;
                    showEvaluation();
                 }
             })
            .create();
    	}
        return new AlertDialog.Builder(Test.this)
        .setTitle("Info").setMessage(intro)
        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
            	state.question = 0;
            	state.counterTime = SystemClock.uptimeMillis();
                		buildQuestionView();
               handler.removeCallbacks(updateTimeTask);
               handler.postDelayed(updateTimeTask, 100);
            }
        })
        .create();

    }
	
    private Runnable updateTimeTask = new Runnable() {
    	   public void run() {   		   
    	       final long start = state.counterTime;
    	       long millis = (start + state.runtime) - SystemClock.uptimeMillis()  ;
    	       int seconds = (int) (millis / 1000);
    	       int minutes = seconds / 60;
    	       seconds     = seconds % 60;
    	
    	       if (seconds < 10) {
    	    	   timer.setText("" + minutes + ":0" + seconds);
    	       } else {
    	    	   timer.setText("" + minutes + ":" + seconds);       
    	       }
    	      
    	       if(millis > 0 && !state.freeze){
    	       handler.postAtTime(this,
    	    		   SystemClock.uptimeMillis() + 1000 );
    	       }else{
    	    	   if(millis<=0){
    	    	   Toast.makeText(getBaseContext(), 
    	    			   Constants.PREFERENCES_LANGUAGE_CODE_DE.equals(languagecode)?
    	    			  R.string.time_over_message_de:R.string.time_over_message_en, 
    	                    Toast.LENGTH_LONG).show();
    	    	   }
    	    	   timer.setText("");       
    	    	   handler.removeCallbacks(updateTimeTask);
    	       }
    	   }
    	};

	@Override
	protected void onPause() {
		super.onPause();
		timer.setText("");     
		handler.removeCallbacks(updateTimeTask);
		Log.v(Constants.LOGTAG,"onPause called");
	}
	

	@Override
	protected void onResume() {
		super.onResume();
		if(!state.freeze && (( state.counterTime + state.runtime) - SystemClock.uptimeMillis() ) > 0 ){
			handler.postDelayed(updateTimeTask, 100);
			Log.v(Constants.LOGTAG,"onResume called reactivate handler");	
		}
		Log.v(Constants.LOGTAG,"onResume called");
	}

	@Override
	public void onSaveInstanceState(Bundle savedInstanceState) {
		Log.v(Constants.LOGTAG,"onSaveInstanceState called");
	  savedInstanceState.putSerializable(Constants.STATE, state);
	  handler.removeCallbacks(updateTimeTask);
	  super.onSaveInstanceState(savedInstanceState);
	}


	
}
